package com.test.study.shiro_demo.config;

import com.test.study.shiro_demo.dao.*;
import com.test.study.shiro_demo.entity.TRolePerms;
import com.test.study.shiro_demo.entity.TUser;
import com.test.study.shiro_demo.entity.TUserRole;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Component
public class MyRelam extends AuthorizingRealm {
    @Autowired(required =false)
    @Lazy
    private TUserDao tUserDao;
    @Autowired(required =false)
    @Lazy
    private TRoleDao tRoleDao;
    @Autowired(required =false)
    @Lazy
    private TUserRoleDao tUserRoleDao;
    @Autowired(required =false)
    @Lazy
    private TPermsDao tPermsDao;
    @Autowired(required =false)
    @Lazy
    private TRolePermsDao tRolePermsDao;
    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("自定义认证开始");
        // 用户名密码(暂时先自定义一个做测试)
        TUser tUser = new TUser();

        String principal = (String) authenticationToken.getPrincipal();
        //通过参数获取登录的控制器中生成的 令牌
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        //查询数据库有无对应的实体类
        TUser entity = tUserDao.getByEntity(tUser.setUname(token.getUsername()));
        System.out.println(entity.toString());
        if(entity==null){
            return null;
        }
        //2.判断密码
        //1).principal:认证的实体类信息。可以是username，也可以是数据表对应的用户的体类对象
        //2).credentials:密码（数据库获取的用户的密码）
        //User user=userService.findUserByName(userToken.getUsername());
        //Object credentials=user.getPassword();
        //3).realmName：当前realm对象的name，调用父类的getName()方法即可
      	//4).盐值ByteSource credentialsSalt = ByteSource.Util.bytes(user.getName());
        // 盐值 要唯一
        return new SimpleAuthenticationInfo(principal,entity.getPwd(),this.getName());
    }

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行自定义授权方法");
        //1、查询当前认证的用户信息
        String uname = (String)principalCollection.getPrimaryPrincipal();
        //1、查询当前用户具备的权限信息;
        //使用集合进行过滤perms
        Set<String> listPerms=new HashSet<>();
        List<String> listRoles=new ArrayList<>();
        TUser tUser = new TUser().setUname(uname);
        //根据用户名获取用户id
        Integer uid = tUserDao.getByEntity(tUser).getUid();
        TUserRole tUserRole = new TUserRole().setUid(uid);
        //根据用户id获取角色信息(一个用户可能会有多角色)
        List<Integer> rids=new ArrayList<>();
        tUserRoleDao.listByEntity(tUserRole).forEach(item->
                rids.add(item.getRid()));
        tRoleDao.listByIds(rids).forEach(item->
                listRoles.add(item.getRname())
                );
        System.out.println("listRoles: "+listRoles);
        List<TRolePerms> tRolePerms=new ArrayList<>();
        //遍历角色信息获取对应的权限信息
        for (int i = 0; i < rids.size(); i++) {
            Integer rid=rids.get(i);
            tRolePerms.addAll(tRolePermsDao.listByEntity(new TRolePerms().setRid(rid))) ;
        }
        //根据pid获取对应的权限信息
        List<Integer> pids=new ArrayList<>();
        tRolePerms.forEach(item-> pids.add(item.getPid()));
        tPermsDao.listByIds(pids).forEach(item-> listPerms.add(item.getPname()));

        //2、将用户的权限信息给shiro
        SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
        //添加权限信息
        info.addStringPermissions(listPerms);
        //添加角色信息
        info.addRoles(listRoles);
        //3、返回当前用户具备权限
        return info;
    }


}
